#include <include/stdio.h>
#include <include/pic.h>
#include <include/x86.h>
#include <include/memlayout.h>
#include <include/trap.h>

#define NR_IDT	256
struct Gatedesc idt[NR_IDT];
struct Pseudodesc idt_pd={
	sizeof(idt)-1,(uint32_t)idt
};

// return the trap description from a trap number.
static const char *
trapname(int trapno)
{
	static const char * const excnames[] = {
		"#DE:Divide error",
		"#DB:Debug",
		"--:Non-Maskable Interrupt",
		"#BP:Breakpoint",
		"#OF:Overflow",
		"#BR:BOUND Range Exceeded",
		"#UD:Invalid Opcode",
		"#NM:Device Not Available",
		"#DF:Double Falt",
		"--:Coprocessor Segment Overrun",
		"#TS:Invalid TSS",
		"#NP:Segment Not Present",
		"#SS:Stack Fault",
		"#GP:General Protection",
		"#PF:Page Fault",
		"--:(unknown trap)",
		"#MF:x87 FPU Floating-Point Error",
		"#AC:Alignment Check",
		"#MC:Machine-Check",
		"#XF:SIMD Floating-Point Exception"
	};

	if (trapno<sizeof(excnames)/sizeof(excnames[0]))
		return excnames[trapno];
	if (trapno==T_SYSCALL)
		return "System call";
	return "(unknown trap)";
}
void
init_idt(void)
{
	pic_init();
	extern void isr0();// divide error	
	extern void isr1();// debug exception
	extern void isr2();// non-maskable interrupt
	extern void isr3();// breakpoint
	extern void isr4();// overflow
	extern void isr5();// bounds check
	extern void isr6();// illegal opcode
	extern void isr7();// device not available 
	extern void isr8();// double fault
	extern void isr9();// reserved (not generated by recent processors)
	extern void isr10();// invalid task switch segment
	extern void isr11();// segment not present
	extern void isr12();// stack exception
	extern void isr13();// general protection fault
	extern void isr14();// page fault
	extern void isr15();// reserved
	extern void isr16();// floating point error
	extern void isr17();// aligment check
	extern void isr18();// machine check
	extern void isr19();// SIMD floating point error

	// hardware interrupts
	extern void irq0();
	extern void irq1();
	extern void irq2();
	extern void irq3();
	extern void irq4();
	extern void irq5();
	extern void irq6();
	extern void irq7();
	extern void irq8();
	extern void irq9();
	extern void irq10();
	extern void irq11();
	extern void irq12();
	extern void irq13();
	extern void irq14();

	extern void syscall_entry();//syscall
//设置IDT
	SETGATE(idt[0],1,GD_KT,isr0,0);
	SETGATE(idt[1],1,GD_KT,isr1,0);
	SETGATE(idt[2],1,GD_KT,isr2,0);
	SETGATE(idt[3],1,GD_KT,isr3,3);
	SETGATE(idt[4],1,GD_KT,isr4,0);
	SETGATE(idt[5],1,GD_KT,isr5,0);
	SETGATE(idt[6],1,GD_KT,isr6,0);
	SETGATE(idt[7],1,GD_KT,isr7,0);
	SETGATE(idt[8],1,GD_KT,isr8,0);
	SETGATE(idt[9],1,GD_KT,isr9,0);
	SETGATE(idt[10],1,GD_KT,isr10,0);
	SETGATE(idt[11],1,GD_KT,isr11,0);
	SETGATE(idt[12],1,GD_KT,isr12,0);
	SETGATE(idt[13],1,GD_KT,isr13,0);
	SETGATE(idt[14],1,GD_KT,isr14,0);
	SETGATE(idt[15],1,GD_KT,isr15,0);
	SETGATE(idt[16],1,GD_KT,isr16,0);
	SETGATE(idt[17],1,GD_KT,isr17,0);
	SETGATE(idt[18],1,GD_KT,isr18,0);
	SETGATE(idt[19],1,GD_KT,isr19,0);
	// hardware interrupts
	SETGATE(idt[INT_VECTOR_IRQ0],0,GD_KT,irq0,0);
	SETGATE(idt[INT_VECTOR_IRQ0+1],0,GD_KT,irq1,0);
	SETGATE(idt[INT_VECTOR_IRQ0+2],0,GD_KT,irq2,0);
	SETGATE(idt[INT_VECTOR_IRQ0+3],0,GD_KT,irq3,0);
	SETGATE(idt[INT_VECTOR_IRQ0+4],0,GD_KT,irq4,0);
	SETGATE(idt[INT_VECTOR_IRQ0+5],0,GD_KT,irq5,0);
	SETGATE(idt[INT_VECTOR_IRQ0+6],0,GD_KT,irq6,0);
	SETGATE(idt[INT_VECTOR_IRQ0+7],0,GD_KT,irq7,0);
	SETGATE(idt[INT_VECTOR_IRQ0+8],0,GD_KT,irq8,0);
	SETGATE(idt[INT_VECTOR_IRQ0+9],0,GD_KT,irq9,0);
	SETGATE(idt[INT_VECTOR_IRQ0+10],0,GD_KT,irq10,0);
	SETGATE(idt[INT_VECTOR_IRQ0+11],0,GD_KT,irq11,0);
	SETGATE(idt[INT_VECTOR_IRQ0+12],0,GD_KT,irq12,0);
	SETGATE(idt[INT_VECTOR_IRQ0+13],0,GD_KT,irq13,0);
	SETGATE(idt[INT_VECTOR_IRQ0+14],0,GD_KT,irq14,0);
	//系统调用T_SYSCALL=48
	SETGATE(idt[48],0,GD_KT,syscall_entry,3);

	__asm __volatile("lidt idt_pd");
}

/*
 * isr of our interupts..
 */
void
trap(struct Trapframe *tf)
{
	if (tf->tf_trapno<20) {
		cprintf("Exception:%s:%d\n",trapname(tf->tf_trapno),tf->tf_trapno);
		cprintf("EFLAGS:0x%x,CS:0x%x,EIP:0x%x\n",tf->tf_eflags,tf->tf_cs,tf->tf_eip);
	
		if (tf->tf_err!=0xFFFFFFFF) {
			cprintf("Error code:0x%x\n",tf->tf_err);
		}
	}
	else {
		int irq=tf->tf_trapno-INT_VECTOR_IRQ0;
		(irq_table[irq])(tf);
	}
}
